]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOS9/Mac OS Test Searcher.c
mDNSResponder-58.1.tar.gz
[apple/mdnsresponder.git] / mDNSMacOS9 / Mac OS Test Searcher.c
1 /*
2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24
25 Change History (most recent first):
26
27 $Log: Mac\040OS\040Test\040Searcher.c,v $
28 Revision 1.13 2003/08/14 02:19:54 cheshire
29 <rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
30
31 Revision 1.12 2003/08/12 19:56:24 cheshire
32 Update to APSL 2.0
33
34 */
35
36 #include <stdio.h> // For printf()
37 #include <Events.h> // For WaitNextEvent()
38 #include <SIOUX.h> // For SIOUXHandleOneEvent()
39
40 #include "mDNSClientAPI.h" // Defines the interface to the client layer above
41 #include "mDNSMacOS9.h" // Defines the specific types needed to run mDNS on this platform
42
43 typedef struct
44 {
45 OTLIFO serviceinfolist;
46 Boolean headerPrinted;
47 Boolean lostRecords;
48 } SearcherServices;
49
50 typedef struct { ServiceInfo i; mDNSBool add; mDNSBool dom; OTLink link; } linkedServiceInfo;
51
52 // These don't have to be globals, but their memory does need to remain valid for as
53 // long as the search is going on. They are declared as globals here for simplicity.
54 #define RR_CACHE_SIZE 1000
55 static CacheRecord rrcachestorage[RR_CACHE_SIZE];
56 static mDNS mDNSStorage;
57 static mDNS_PlatformSupport PlatformSupportStorage;
58 static SearcherServices services;
59 static DNSQuestion browsequestion, domainquestion;
60
61 // PrintServiceInfo prints the service information to standard out
62 // A real application might want to do something else with the information
63 static void PrintServiceInfo(SearcherServices *services)
64 {
65 OTLink *link = OTReverseList(OTLIFOStealList(&services->serviceinfolist));
66
67 while (link)
68 {
69 linkedServiceInfo *ls = OTGetLinkObject(link, linkedServiceInfo, link);
70 ServiceInfo *s = &ls->i;
71
72 if (!services->headerPrinted)
73 {
74 printf("%-55s Type Domain IP Address Port Info\n", "Name");
75 services->headerPrinted = true;
76 }
77
78 if (ls->dom)
79 {
80 char c_dom[256];
81 ConvertDomainNameToCString(&s->name, c_dom);
82 if (ls->add) printf("%-55s available for browsing\n", c_dom);
83 else printf("%-55s no longer available for browsing\n", c_dom);
84 }
85 else
86 {
87 domainlabel name;
88 domainname type, domain;
89 UInt16 port = (UInt16)((UInt16)s->port.b[0] << 8 | s->port.b[1]);
90 char c_name[64], c_type[256], c_dom[256], c_ip[20];
91
92 DeconstructServiceName(&s->name, &name, &type, &domain);
93 ConvertDomainLabelToCString_unescaped(&name, c_name);
94 ConvertDomainNameToCString(&type, c_type);
95 ConvertDomainNameToCString(&domain, c_dom);
96 sprintf(c_ip, "%d.%d.%d.%d", s->ip.ip.v4.b[0], s->ip.ip.v4.b[1], s->ip.ip.v4.b[2], s->ip.ip.v4.b[3]);
97
98 printf("%-55s %-16s %-14s ", c_name, c_type, c_dom);
99 if (ls->add) printf("%-15s %5d %#s\n", c_ip, port, s->TXTinfo);
100 else printf("Removed\n");
101 }
102
103 link = link->fNext;
104 OTFreeMem(ls);
105 }
106 }
107
108 // When the name, address, port, and txtinfo for a service is found, FoundInstanceInfo()
109 // enqueues a record for PrintServiceInfo() to print.
110 // Note, a browsing application would *not* normally need to get all this information --
111 // all it needs is the name, to display to the user.
112 // Finding out the address, port, and txtinfo should be deferred to the time that the user
113 // actually needs to contact the service to use it.
114 static void FoundInstanceInfo(mDNS *const m, ServiceInfoQuery *query)
115 {
116 SearcherServices *services = (SearcherServices *)query->ServiceInfoQueryContext;
117 linkedServiceInfo *info = (linkedServiceInfo *)(query->info);
118 if (query->info->ip.type == mDNSAddrType_IPv4)
119 {
120 mDNS_StopResolveService(m, query); // For this test code, one answer is sufficient
121 OTLIFOEnqueue(&services->serviceinfolist, &info->link);
122 OTFreeMem(query);
123 }
124 }
125
126 // When a new named instance of a service is found, FoundInstance() is called.
127 // In this sample code we turn around and immediately issue a query to resolve that service name to
128 // find its address, port, and txtinfo, but a normal browing application would just display the name.
129 static void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
130 {
131 #pragma unused (question)
132 SearcherServices *services = (SearcherServices *)question->QuestionContext;
133 linkedServiceInfo *info;
134
135 debugf("FoundInstance %##s PTR %##s", answer->name.c, answer->rdata->u.name.c);
136
137 if (answer->rrtype != kDNSType_PTR) return;
138 if (!services) { debugf("FoundInstance: services is NULL"); return; }
139
140 info = (linkedServiceInfo *)OTAllocMem(sizeof(linkedServiceInfo));
141 if (!info) { services->lostRecords = true; return; }
142
143 info->i.name = answer->rdata->u.name;
144 info->i.InterfaceID = answer->InterfaceID;
145 info->i.ip.type = mDNSAddrType_IPv4;
146 info->i.ip.ip.v4 = zeroIPAddr;
147 info->i.port = zeroIPPort;
148 info->add = AddRecord;
149 info->dom = mDNSfalse;
150
151 if (!AddRecord) // If TTL == 0 we're deleting a service,
152 OTLIFOEnqueue(&services->serviceinfolist, &info->link);
153 else // else we're adding a new service
154 {
155 ServiceInfoQuery *q = (ServiceInfoQuery *)OTAllocMem(sizeof(ServiceInfoQuery));
156 if (!q) { OTFreeMem(info); services->lostRecords = true; return; }
157 mDNS_StartResolveService(m, q, &info->i, FoundInstanceInfo, services);
158 }
159 }
160
161 static void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
162 {
163 #pragma unused (m)
164 #pragma unused (question)
165 SearcherServices *services = (SearcherServices *)question->QuestionContext;
166 linkedServiceInfo *info;
167
168 debugf("FoundDomain %##s PTR %##s", answer->name.c, answer->rdata->u.name.c);
169
170 if (answer->rrtype != kDNSType_PTR) return;
171 if (!services) { debugf("FoundDomain: services is NULL"); return; }
172
173 info = (linkedServiceInfo *)OTAllocMem(sizeof(linkedServiceInfo));
174 if (!info) { services->lostRecords = true; return; }
175
176 info->i.name = answer->rdata->u.name;
177 info->i.InterfaceID = answer->InterfaceID;
178 info->i.ip.type = mDNSAddrType_IPv4;
179 info->i.ip.ip.v4 = zeroIPAddr;
180 info->i.port = zeroIPPort;
181 info->add = AddRecord;
182 info->dom = mDNStrue;
183
184 OTLIFOEnqueue(&services->serviceinfolist, &info->link);
185 }
186
187 // YieldSomeTime() just cooperatively yields some time to other processes running on classic Mac OS
188 static Boolean YieldSomeTime(UInt32 milliseconds)
189 {
190 extern Boolean SIOUXQuitting;
191 EventRecord e;
192 WaitNextEvent(everyEvent, &e, milliseconds / 17, NULL);
193 SIOUXHandleOneEvent(&e);
194 return(SIOUXQuitting);
195 }
196
197 int main()
198 {
199 extern void mDNSPlatformIdle(mDNS *const m); // Only needed for debugging version
200 mStatus err;
201 Boolean DoneSetup = false;
202
203 SIOUXSettings.asktosaveonclose = false;
204 SIOUXSettings.userwindowtitle = "\pMulticast DNS Searcher";
205 SIOUXSettings.rows = 40;
206 SIOUXSettings.columns = 132;
207
208 printf("Prototype Multicast DNS Searcher\n\n");
209 printf("WARNING! This is experimental software.\n\n");
210 printf("Multicast DNS is currently an experimental protocol.\n\n");
211 printf("This software reports errors using MacsBug breaks,\n");
212 printf("so if you don't have MacsBug installed your Mac may crash.\n\n");
213 printf("******************************************************************************\n");
214
215 err = InitOpenTransport();
216 if (err) { debugf("InitOpenTransport failed %d", err); return(err); }
217
218 err = mDNS_Init(&mDNSStorage, &PlatformSupportStorage, rrcachestorage, RR_CACHE_SIZE,
219 mDNS_Init_DontAdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
220 if (err) return(err);
221
222 services.serviceinfolist.fHead = NULL;
223 services.headerPrinted = false;
224 services.lostRecords = false;
225
226 while (!YieldSomeTime(35))
227 {
228 // For debugging, use "#define __ONLYSYSTEMTASK__ 1" and call mDNSPlatformIdle() periodically.
229 // For shipping code, don't define __ONLYSYSTEMTASK__, and you don't need to call mDNSPlatformIdle()
230 mDNSPlatformIdle(&mDNSStorage); // Only needed for debugging version
231 if (mDNSStorage.mDNSPlatformStatus == mStatus_NoError && !DoneSetup)
232 {
233 domainname srvtype, srvdom;
234 DoneSetup = true;
235 printf("\nSending mDNS service lookup queries and waiting for responses...\n\n");
236 MakeDomainNameFromDNSNameString(&srvtype, "_http._tcp.");
237 MakeDomainNameFromDNSNameString(&srvdom, "local.");
238 err = mDNS_StartBrowse(&mDNSStorage, &browsequestion, &srvtype, &srvdom, mDNSInterface_Any, FoundInstance, &services);
239 if (err) break;
240 err = mDNS_GetDomains(&mDNSStorage, &domainquestion, mDNS_DomainTypeBrowse, mDNSInterface_Any, FoundDomain, &services);
241 if (err) break;
242 }
243
244 if (services.serviceinfolist.fHead)
245 PrintServiceInfo(&services);
246
247 if (services.lostRecords)
248 {
249 services.lostRecords = false;
250 printf("**** Warning: Out of memory: Records have been missed.\n");
251 }
252 }
253
254 mDNS_StopBrowse(&mDNSStorage, &browsequestion);
255 mDNS_Close(&mDNSStorage);
256 return(0);
257 }